/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package argtrust.logic;

import java.util.List;
import java.io.PrintStream;

import aima.core.logic.fol.parsing.ast.Sentence;


import argtrust.util.MyListIterator;

/**
 * An inference node with rule application
 * @author Yuqing Tang
 */
public class RuleInferenceNode extends InferenceNode {

    private MyListIterator<InferenceRule> mRuleIter;
    private InferenceRule mRuleInstance;
    //TODO: Propogate the substitutions upward from the children substitution
    //      into  mConcreteRuleInstance: InferenceRule.
    //private InferenceRule mConcreteRuleInstance;
    /**
     * In the same order as the premises in the inference rule;
     */
    public List<InferenceNode> mChildrenList;
    private int hashCode = 0;
    @Override
    public String toString() {
        return mRuleInstance.toString();
    }

    @Override
    public int hashCode() {
        if (0 == hashCode) {
//            hashCode = 17;
            hashCode = super.hashCode();
            if (mRuleIter != null) {
                hashCode = 37 * hashCode + mRuleIter.hashCode();
            }
            if (mRuleInstance != null) {

                hashCode = 37 * hashCode + mRuleInstance.hashCode();

            }
            if (mChildrenList != null) {
                for (InferenceNode child : mChildrenList) {
                    hashCode = 37 * hashCode + child.hashCode();
                }
            }
        }
        return hashCode;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }


        final RuleInferenceNode rhs = (RuleInferenceNode) obj;
        boolean res = super.equals(obj);
        if (mRuleIter != null) {
            res = res && mRuleIter.equals(rhs.mRuleIter);
        } else {
            res = res && rhs.mRuleIter == null;
        }
        if (mRuleInstance != null) {
            res = res && mRuleInstance.equals(rhs.mRuleInstance);
        } else {
            res = res && rhs.mRuleInstance == null;
        }
        if (mChildrenList != null) {
            res = res && mChildrenList.equals(rhs.mChildrenList);
        } else {
            res = res && rhs.mChildrenList == null;
        }

        return res;

    }

    public RuleInferenceNode() {
    }

    public RuleInferenceNode(RuleInferenceNode orig) {
        mRuleIter = new MyListIterator<InferenceRule>(orig.mRuleIter);
        mRuleInstance = new InferenceRule(orig.mRuleInstance);

    }

    public InferenceRule getRuleInstance() {
        return mRuleInstance;
    }

    public void setRuleInstance(InferenceRule rule_inst) {
        mRuleInstance = rule_inst;
    }

    public MyListIterator<InferenceRule> getRuleIterator() {
        return mRuleIter;
    }

    public void setRuleIterator(MyListIterator<InferenceRule> rule_iter) {
        mRuleIter = rule_iter;
    }

    public void addChild(InferenceNode inf) {
        mChildrenList.add(inf);
    }

    public void setChildrenList(List<InferenceNode> list) {
        mChildrenList = list;
    }

    public List<InferenceNode> getChildrenList() {
        return mChildrenList;
    }

    public void debug_print(PrintStream out) {
//        out.println("RuleInferenceNode::debug_print");
        mRuleInstance.debug_print(out);
        for (InferenceNode inf_node : mChildrenList) {
            inf_node.debug_print(out);
        }
    }

    
    @Override
    public void unmarkHierarchy() {
        unmark();
        for (InferenceNode next_node : mChildrenList) {
            if (next_node.isMark()) {
                next_node.unmarkHierarchy();
            }
        }
    }
}
